package com.zzmm.socket.demo;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import org.junit.Test;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Scanner;

public class HomeworkTest {

    final String q1 = "name";
    final String q2 = "hobby";

    public static void main01(String[] args) {
        // junit不支持控制台输入
        new HomeworkTest().testHomeWork01TCPClient();
    }

    @SneakyThrows
    @Test
    public void testHomeWork01TCPService() {
        ServerSocket serverSocket = new ServerSocket(9999);

        while (!serverSocket.isClosed()) {
            System.out.println("等待客户端连接...");
            Socket clientSocket = serverSocket.accept();

            // new Thread(() -> {

            try (
                    BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()))
            ) {

                // 读取客户端问题
                String req = reader.readLine();
                System.out.printf("接收到客户端请求：%s", req);

                // 响应客户端
                writer.write(answer(req));
                writer.newLine();
                writer.flush();

                clientSocket.close();
                System.out.println("\n通信结束");
            } catch (IOException e) {
                e.printStackTrace();
            }


            // }).start();


        }

    }

    @SneakyThrows
    @Test
    public void testHomeWork01TCPClient() {

        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.print("请输入问题：");
            String q = scanner.next();

            try (
                    Socket socket = new Socket("192.168.7.1", 9999);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
            ) {

                // 发送问题
                writer.write(q);
                writer.newLine(); // 换行，方便客户端读一行
                writer.flush();

                // 接收服务端响应
                String resp = reader.readLine();
                System.out.printf("服务端响应：%s", resp);

                System.out.println("\n通信结束");
                System.out.println();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public String answer(String q) {
        switch (q) {
            case q1:
                return "我是zzmm";
            case q2:
                return "编写Java程序";
            default:
                return "你说啥呢";
        }

    }

    @SneakyThrows
    @Test
    public void testHomeWork02UDPSender() {
        // 监听端口
        DatagramSocket datagramSocket = new DatagramSocket(7777);

        for (int i = 0; i < 10; i++) {
            // 发送数据包
            InetAddress receiverAddress = InetAddress.getByName("192.168.7.1");
            byte[] data = RandomUtil.randomBoolean() ? "四大名著有那些".getBytes(StandardCharsets.UTF_8) : RandomUtil.randomBytes(8);
            DatagramPacket datagramPacket = new DatagramPacket(data, data.length, receiverAddress, 8888);
            datagramSocket.send(datagramPacket);

            // 接收数据包
            data = new byte[1024];
            datagramPacket.setData(data);
            datagramSocket.receive(datagramPacket);

            // 获取响应
            System.out.println("接收端回复：" + new String(datagramPacket.getData(), 0, datagramPacket.getLength()));

            Thread.sleep(1000);
        }

        // 释放资源
        datagramSocket.close();
    }

    @SneakyThrows
    @Test
    public void testHomeWork02UDPReceiver() {
        // 监听端口
        DatagramSocket datagramSocket = new DatagramSocket(8888);

        for (int i = 0; i < 10; i++) {
            // 接收数据包
            byte[] data = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
            datagramSocket.receive(datagramPacket);

            // 回复
            String question = new String(datagramPacket.getData(), 0, datagramPacket.getLength());
            System.out.printf("发送端的问题是：%s\n", question);
            String answer = question.equals("四大名著有那些")
                    ? "四大名著是：《红楼梦》、《西游记》、《三国演义》、《水浒传》" : "what?";
            datagramPacket.setData(answer.getBytes(StandardCharsets.UTF_8));
            datagramSocket.send(datagramPacket);
        }

        // 释放资源
        datagramSocket.close();
    }

    @Getter
    @AllArgsConstructor
    private enum Image {

        SUN_FLOWER("向日葵", "src/main/resources/向日葵.jpg"),
        MOUNTAIN_VILLA("避暑山庄", "src/main/resources/避暑山庄.png"),
        HACKER("黑客", "src/main/resources/黑客.jpg"),
        DEFAULT("默认", "src/main/resources/default.png");

        private final String name;
        private final String url;

        public static Image getByName(String name) {
            return Arrays.stream(Image.values())
                    .filter(each -> ObjectUtil.equals(each.name, name))
                    .findFirst()
                    .orElse(DEFAULT);
        }

    }


    @SneakyThrows
    @Test
    public void testHomeWork03TCPDownloadServer() {
        // 端口监听
        ServerSocket serverSocket = new ServerSocket(9999);

        // 处理客户端请求
        while (!serverSocket.isClosed()) {
            System.out.println("等待客户端连接...");
            // 接收连接
            Socket socket = serverSocket.accept();

            // 读取客户端请求，获取文件地址
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String req = reader.readLine();
            System.out.println("接收到客户端请求：" + req);
            Image image = Image.getByName(req);

            // 从服务器读取文件，发送给客户端
            BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(image.url));
            BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
            byte[] data = new byte[1024];
            int len;
            while ((len = inputStream.read(data)) != -1) {
                outputStream.write(data, 0, len);
            }
            outputStream.flush();
            socket.shutdownOutput();
            System.out.println("文件发送成功");

            // 释放资源，关闭连接
            System.out.println();
            outputStream.close();
            inputStream.close();
            reader.close();
            socket.close();
        }

        serverSocket.close();
    }

    public static void main(String[] args) {
        new HomeworkTest().testHomeWork03TCPDownloadClient();
    }

    @SneakyThrows
    @Test
    public void testHomeWork03TCPDownloadClient() {
        // 读取控制台参数
        Scanner scanner = new Scanner(System.in);

        while (true) {
            // 与服务器建立连接
            Socket socket = new Socket(InetAddress.getByName("192.168.7.1"), 9999);

            // 读取参数
            System.out.print("请输入要下载的图片名称：");
            String req = scanner.next();

            // 发送请求
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            writer.write(req);
            writer.newLine();
            writer.flush();

            // 接收文件，拷贝到本地文件夹
            String path = "D:\\Users\\Longgr\\Desktop\\filetest\\" + req + ".jpg";
            BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
            BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(path));
            byte[] data = new byte[1024];
            int len;
            while ((len = inputStream.read(data)) != -1) {
                outputStream.write(data, 0, len);
            }
            outputStream.flush();
            System.out.println("文件下载成功：" + path);

            // 释放资源
            System.out.println();
            outputStream.close();
            inputStream.close();
            writer.close();
            socket.close();
        }

    }


}
